home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
EDITORS
/
MEMACS
/
C
/
Riscos
< prev
next >
Wrap
Text File
|
1990-07-11
|
18KB
|
901 lines
/* RISCOS.C: Operating specific I/O and Spawning functions
under the RISC OS operating system
for MicroEMACS 3.10
(C)opyright 1988 by Daniel M. Lawrence
*/
#include <stdio.h>
#include "estruct.h"
#include "eproto.h"
#ifdef RISCOS
#include "edef.h"
#include "elang.h"
#include <stdlib.h>
#include <time.h>
#include "filter.h"
#include "kernel.h"
#include "swis.h"
extern char *dirscan (char *);
static int bufread (BUFFER *, FILE *);
static int fgetline (FILE *, char **, int *);
static void shell (void);
static int extchar (int, int);
/* Switch escape off and on, from C.Archimedes */
extern void esc_off(void);
extern void esc_on(void);
static _kernel_swi_regs regs;
#define fx(a,x,y) (_kernel_osbyte(a,x,y))
#define checkkey(k) ((fx(121, (k) ^ 0x80, 0) & 0xFF) != 0)
#define swi(n) (_kernel_swi(n,®s,®s))
#define vdu(n) (void)(_kernel_oswrch(n))
#define vdu23(a,b,c,d,e,f,g,h,i) \
(void)( \
_kernel_oswrch(23), \
_kernel_oswrch(a), \
_kernel_oswrch(b), \
_kernel_oswrch(c), \
_kernel_oswrch(d), \
_kernel_oswrch(e), \
_kernel_oswrch(f), \
_kernel_oswrch(g), \
_kernel_oswrch(h), \
_kernel_oswrch(i) \
)
/* Some global variables */
#define INBUFSIZ 40
/* input buffers and pointers */
#define IBUFSIZE 64 /* this must be a power of 2 */
unsigned char in_buf[IBUFSIZE]; /* input character buffer */
int in_next = 0; /* pos to retrieve next input character */
int in_last = 0; /* pos to place most recent input character */
void in_init (void) /* initialize the input buffer */
{
in_next = in_last = 0;
}
int in_check (void) /* is the input buffer non-empty? */
{
if (in_next == in_last)
return(FALSE);
else
return(TRUE);
}
void in_put (int event)
{
in_buf[in_last++] = event;
in_last &= (IBUFSIZE - 1);
}
int in_get (void) /* get an event from the input buffer */
{
register int event; /* event to return */
event = in_buf[in_next++];
in_next &= (IBUFSIZE - 1);
return(event);
}
/* This function is called once to set up the terminal device streams.
*/
int ttopen (void)
{
ttrow = 999;
ttcol = 999;
in_init();
return 0;
}
/* Write a character to the display. On VMS, terminal output is buffered, and
* we just put the characters in the big array, after checking for overflow.
* On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
* MS-DOS (use the very very raw console output routine).
*/
int ttputc (int c)
{
vdu(c);
return 0;
}
/* Flush terminal buffer. Does real work where the terminal output is buffered
* up. A no-operation on systems where byte at a time terminal I/O is done.
*/
int ttflush (void)
{
return 0;
}
/* Get a character from the operating system. If it is a special key code,
* return the initial 0 of the Emacs extended code, and push the remaining
* part of the code sequence into the input buffer.
*/
int oschar (void)
{
int ch = _kernel_osrdch();
int alt = 0;
/* Check for ALT */
if (ch == 0x7F)
{
alt = ALTD;
ch = _kernel_osrdch();
}
/* For non-function keys, simply return them */
if (ch != 0 && alt == 0)
return ch;
/* For ALT-normal keys, return 0, ALT, char (upper case) */
if (ch != 0)
{
in_put(alt >> 8);
in_put(upperc(ch));
return(0);
}
/* Skip the null byte */
ch = _kernel_osrdch();
/* A genuine null gets returned as 0, 0 */
if (ch == 0)
{
in_put(0);
return(0);
}
/* For function keys, convert to an extended character */
ch = extchar(alt, ch);
/* Check for a simple character */
if ((ch >> 8) == 0)
return(ch);
/* Otherwise, return an extended sequence */
in_put(ch >> 8);
in_put(ch & 0xFF);
return(0);
}
/* Read a character from the terminal, performing no editing and doing no echo
* at all. Also mouse events are forced into the input stream here.
*/
int ttgetc (void)
{
register int c; /* character read */
/* return any keystrokes waiting in the type ahead buffer */
if (in_check())
return(in_get());
return(oschar());
}
#if TYPEAH
/* Check to see if any characters are already in the keyboard buffer.
*/
int typahead (void)
{
int result;
result = fx(152,0,0);
if (result & 0x0F00)
return(FALSE);
else
return(TRUE);
}
#endif
/*
* Create a subjob with a copy of the command intrepreter in it. When the
* command interpreter exits, mark the screen as garbage so that you do a full
* repaint. Bound to "^X C".
*/
int spawncli (int f, int n)
{
/* don't allow this command if restricted */
if (restflag)
return(resterr());
movecursor(term.t_nrow, 0); /* Seek to last line. */
TTflush();
TTkclose();
shell();
TTkopen();
sgarbf = TRUE;
return(TRUE);
}
/*
* Run a one-liner in a subjob. When the command returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X !".
*/
int spawn (int f, int n)
{
register int s;
char line[NLINE];
/* don't allow this command if restricted */
if (restflag)
return(resterr());
strcpy(line, "Call:");
if ((s=mlreply("!", &line[5], NLINE-5)) != TRUE)
return(s);
movecursor(term.t_nrow - 1, 0);
TTkclose();
system(line);
TTkopen();
/* if we are interactive, pause here */
if (clexec == FALSE) {
mlputs(TEXT6);
/* "\r\n\n[End]" */
tgetc();
}
sgarbf = TRUE;
return (TRUE);
}
/*
* Run an external program with arguments. When it returns, wait for a single
* character to be typed, then mark the screen as garbage so a full repaint is
* done. Bound to "C-X $".
*/
int execprg (int f, int n)
{
register int s;
char line[NLINE];
/* don't allow this command if restricted */
if (restflag)
return(resterr());
strcpy(line, "Call:");
if ((s=mlreply("$", &line[5], NLINE-5)) != TRUE)
return(s);
movecursor(term.t_nrow - 1, 0);
TTkclose();
system(line);
TTkopen();
/* if we are interactive, pause here */
if (clexec == FALSE) {
mlputs(TEXT6);
/* "\r\n\n[End]" */
tgetc();
}
sgarbf = TRUE;
return (TRUE);
}
/*
* Pipe a one line command into a window
* Bound to ^X @
*/
int pipecmd (int f, int n)
{
register WINDOW *wp; /* pointer to new window */
register BUFFER *bp; /* pointer to buffer to zot */
int s; /* command status */
char line[NLINE]; /* command line send to shell */
FILTER *flt; /* command filter */
static char bname[] = "command";
/* don't allow this command if restricted */
if (restflag)
return(resterr());
if ((flt = FLTopen()) == NULL)
return(FALSE);
/* get the command to pipe in */
if (mlreply("@", line, NLINE) != TRUE)
return(FALSE);
/* get rid of the command output buffer if it exists */
if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
/* try to make sure we are off screen */
wp = wheadp;
while (wp != NULL) {
if (wp->w_bufp == bp) {
onlywind(FALSE, 1);
break;
}
wp = wp->w_wndp;
}
/* get rid of the existing command buffer */
if (zotbuf(bp) != TRUE)
return(FALSE);
}
movecursor(term.t_nrow - 1, 0);
/* execute the command */
TTkclose();
s = FLTfilter(flt,line);
TTkopen();
sgarbf = TRUE;
/* did the output file get generated? */
if (s == FILTER_ERROR)
{
FLTclose(flt);
return(FALSE);
}
/* split the current window to make room for the command output */
if (splitwind(FALSE, 1) == FALSE)
{
FLTclose(flt);
return(FALSE);
}
/* create a new buffer for the output */
if ((bp = bfind(bname, TRUE, BFINVS)) == FALSE)
{
FLTclose(flt);
return(FALSE);
}
/* and read the stuff in */
if (bufread(bp,FLTout(flt)) == FALSE)
{
FLTclose(flt);
return(FALSE);
}
FLTclose(flt);
/* make this window in VIEW mode, update all mode lines */
bp->b_mode |= MDVIEW;
wp = wheadp;
while (wp != NULL) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
return(TRUE);
}
/*
* filter a buffer through an external DOS program
* Bound to ^X #
*/
int filter (int f, int n)
{
register int s; /* return status from CLI */
char line[NLINE]; /* command line send to shell */
LINE *lp; /* Temporary line pointer */
FILTER *flt; /* Command filter */
register int i;
/* don't allow this command if restricted */
if (restflag)
return(resterr());
if (curbp->b_mode&MDVIEW) /* don't allow this command if */
return(rdonly()); /* we are in read only mode */
if ((flt = FLTopen()) == NULL) {
mlwrite(TEXT2);
/* "[Cannot write filter file]" */
return(FALSE);
}
/* get the filter name and its args */
if ((s=mlreply("#", line, NLINE)) != TRUE)
return(s);
/* copy the current buffer into the filter */
lp = lforw(curbp->b_linep);
while (lp != curbp->b_linep)
{
for (i = 0; i < llength(lp); ++i)
putc(lp->l_text[i], FLTin(flt));
putc('\n', FLTin(flt));
if (ferror(FLTin(flt))) {
FLTclose(flt);
mlwrite(TEXT2);
/* "[Cannot write filter file]" */
return(FALSE);
}
lp = lforw(lp);
}
movecursor(term.t_nrow - 1, 0);
TTkclose();
s = FLTfilter(flt,line);
TTkopen();
sgarbf = TRUE;
/* on failure, escape gracefully */
if (s == FILTER_ERROR || bufread(curbp,FLTout(flt)) == FALSE)
{
FLTclose(flt);
mlwrite(TEXT3);
/* "[Execution failed]" */
return(FALSE);
}
/* Flag the buffer as changed */
curbp->b_flag |= BFCHG;
FLTclose(flt);
return(TRUE);
}
/* Read a file from a supplied file pointer into a specified buffer.
* The buffer's original contents is deleted. FALSE is returned in case
* of errors, TRUE if the read succeeds.
*/
int bufread (BUFFER *bp, FILE *fp)
{
register LINE *lp1;
register LINE *lp2;
register WINDOW *wp;
register int i;
register int s;
int nbytes;
int nline;
int cmark;
char mesg[NSTRING];
char *tline = NULL;
int tlen = 0;
if ((s = bclear(bp)) != TRUE)
return(s);
bp->b_flag &= ~BFCHG;
nline = 0;
while ((s = fgetline(fp, &tline, &tlen)) == FIOSUC)
{
nbytes = strlen(tline);
if ((lp1 = lalloc(nbytes)) == NULL)
{
s = FIOMEM;
break;
}
lp2 = lback(bp->b_linep);
lp2->l_fp = lp1;
lp1->l_fp = bp->b_linep;
lp1->l_bp = lp2;
bp->b_linep->l_bp = lp1;
for (i = 0; i < nbytes; ++i)
lputc(lp1, i, tline[i]);
++nline;
}
if (tline != NULL)
free(tline);
strcpy(mesg,"[");
if (s==FIOERR) {
strcat(mesg, TEXT141);
/* "I/O ERROR, " */
bp->b_flag |= BFTRUNC;
}
if (s == FIOMEM) {
strcat(mesg, TEXT142);
/* "OUT OF MEMORY, " */
bp->b_flag |= BFTRUNC;
}
strcat(mesg, TEXT140);
/* "Read " */
strcat(mesg, int_asc(nline));
strcat(mesg, TEXT143);
/* " line" */
if (nline > 1)
strcat(mesg, "s");
strcat(mesg, "]");
mlwrite(mesg);
for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) {
if (wp->w_bufp == bp) {
wp->w_linep = lforw(bp->b_linep);
wp->w_dotp = lforw(bp->b_linep);
wp->w_doto = 0;
for (cmark = 0; cmark < NMARKS; cmark++) {
wp->w_markp[cmark] = NULL;
wp->w_marko[cmark] = 0;
}
wp->w_flag |= WFMODE|WFHARD;
}
}
if (s == FIOERR || s == FIOFNF) /* False if error. */
return(FALSE);
return(TRUE);
}
/* Read a line from a file, and store the bytes in the supplied buffer.
* Check for I/O errors. Return status.
*/
int fgetline(FILE *fp, char **tline, int *tlen)
{
register int c; /* current character read */
register int i; /* current index into fline */
register char *tmpline; /* temp storage for expanding line */
/* internal copies of the parameters */
register char *tline1 = *tline;
register int tlen1 = *tlen;
/* if we are at the end...return it */
if (feof(fp))
return(FIOEOF);
/* if we don't have an tline, allocate one */
if (tline1 == NULL)
if ((tline1 = malloc(tlen1 = NSTRING)) == NULL)
return(FIOMEM);
/* read the line in */
i = 0;
while ((c = getc(fp)) != EOF && c != '\n') {
tline1[i++] = c;
/* if it's longer, get more room */
if (i >= tlen1) {
if ((tmpline = malloc(tlen1+NSTRING)) == NULL)
{
*tline = tline1;
*tlen = tlen1;
return(FIOMEM);
}
bytecopy(tmpline, tline1, tlen1);
tlen1 += NSTRING;
free(tline1);
tline1 = tmpline;
}
}
#if ST520
if (tline1[i-1] == '\r')
i--;
#endif
/* terminate the string */
tline1[i] = 0;
/* restore the input variables */
*tline = tline1;
*tlen = tlen1;
/* test for any errors that may have occured */
if (c == EOF) {
if (ferror(fp)) {
mlwrite(TEXT158);
/* "File read error" */
return(FIOERR);
}
if (i == 0)
return(FIOEOF);
}
return(FIOSUC);
}
/* Run an interactive operating system shell */
static void shell (void)
{
int len;
_kernel_oserror *err;
char line[261];
strcpy(line, "Call:");
/* Set text window to the full screen */
vdu(26);
/* Set background colour to green and foreground colour to black
* (but do it the opposite way round and apply reverse video, to
* set things up right for 2-colour modes)
*/
#if COLOR
TTbacg(0);
TTforg(2);
TTrev(TRUE);
#endif
/* Clear screen */
vdu(12);
/* Centre on line 0 */
vdu(31);
vdu((term.t_ncol - 14) / 2);
vdu(0);
/* Write the screen title */
regs.r[0] = (int)"Archimedes MOS";
swi(OS_Write0);
/* Define text window, missing top and bottom lines */
vdu(28);
vdu(0);
vdu(term.t_nrow - 1);
vdu(term.t_ncol - 1);
vdu(1);
/* Set background colour to blue and foreground colour to grey */
#if COLOR
TTrev(FALSE);
TTbacg(4);
TTforg(7);
#endif
/* Clear screen */
vdu(12);
for (;;)
{
vdu('*');
regs.r[0] = (int)&line[5];
regs.r[1] = 256;
regs.r[2] = 32;
regs.r[3] = 255;
/* We can't trap ESCAPE here... it acts just like NL */
if ((err = swi(OS_ReadLine)) != NULL)
{
swi(OS_NewLine);
regs.r[0] = (int)err->errmess;
swi(OS_Write0);
swi(OS_NewLine);
continue;
}
len = regs.r[1];
if (len == 0)
break;
line[5+len] = 0;
esc_on();
if (system(line) == -2)
{
char buf[300];
err = _kernel_last_oserror();
sprintf(buf, "%s (Error %d)", err->errmess,
err->errnum);
swi(OS_NewLine);
regs.r[0] = (int)buf;
swi(OS_Write0);
swi(OS_NewLine);
}
esc_off();
}
/* Restore the default text window */
vdu(26);
}
/* return a system dependent string with the current time */
char *timeset (void)
{
register char *sp; /* temp string pointer */
time_t timeval;
time(&timeval);
sp = ctime(&timeval);
sp[strlen(sp)-1] = 0;
return(sp);
}
/* Read a single keypress and return it, converting Risc OS character codes
* into Emacs extended character codes
*/
static int extchar (int alt, int c)
{
int base_key;
int shft = 0;
int ctrl = 0;
/* Save a bit of typing */
#define asc (alt | shft | ctrl)
/* Break the extended code up into parts */
base_key = c & 0xCF;
shft = (c & 0x10 ? SHFT : 0);
ctrl = (c & 0x20 ? CTRL : 0);
/* F1 to F9 (FN1 - FN9) */
if (base_key >= 0x81 && base_key <= 0x89)
return(SPEC | asc | base_key - 0x81 + '1');
switch (base_key)
{
case 0x80: /* F0 (Print) */
return(SPEC | asc | '`');
case 0xCA: /* F10 */
return(SPEC | asc | '0');
case 0xCB: /* F11 */
return(SPEC | asc | '-');
case 0xCC: /* F12 */
return(SPEC | asc | '=');
case 0x8B: /* Copy */
return (SPEC | asc | '>');
case 0x8C: /* Cursor Left */
return (SPEC | asc | 'B');
case 0x8D: /* Cursor Right */
return (SPEC | asc | 'F');
case 0x8E: /* Cursor Down */
return (SPEC | asc | 'N');
case 0x8F: /* Cursor Up */
return (SPEC | asc | 'P');
case 0xCD: /* Insert */
return (SPEC | asc | 'C');
case 0xC1: /* Home */
return (SPEC | asc | '<');
case 0xC2: /* Page Down */
return (SPEC | asc | 'V');
case 0xC3: /* Page Up */
return (SPEC | asc | 'Z');
case 0xC0: /* Delete */
if (asc == 0)
return ('\x7F');
else
return (SPEC | asc | 'D');
case 0x8A: /* Tab */
if (asc == 0)
return ('\t');
else if (!ctrl)
return (alt | shft | CTRL | 'I');
else
return (SPEC | asc | 'T'); /*?????*/
case 0xC4: /* Backspace */
if (asc == 0)
return ('\b');
else if (!ctrl)
return (alt | shft | CTRL | 'H');
else
return (SPEC | asc | 'L'); /*?????*/
case 0xC5: /* Return */
if (asc == 0)
return ('\r');
else if (asc == SHFT)
return ('\n');
else
return (SPEC | asc | 'R');
case 0xC6: /* Enter */
if (asc == 0)
return ('\r');
else if (asc == SHFT)
return ('\n');
else
return (SPEC | asc | 'E');
}
/* Anything else, return as itself */
return (alt | c);
#undef asc
}
#if FTYPE
/* File type routines */
void PASCAL NEAR fsettype (char *fname, int type)
{
regs.r[0] = 18;
regs.r[1] = (int)fname;
regs.r[2] = type;
swi(OS_File);
}
int PASCAL NEAR fgettype (char *fname)
{
regs.r[0] = 5;
regs.r[1] = (int)fname;
if (swi(OS_File))
return(0xFFF);
if ((regs.r[2] & 0xFFF00000) != 0xFFF00000)
return(0xFFF);
return((regs.r[2] >> 8) & 0xFFF);
}
int PASCAL NEAR maketype (char *type)
{
regs.r[0] = 31;
regs.r[1] = (int)type;
if (swi(OS_FSControl))
return(0xFFF);
return(regs.r[2]);
}
#endif
/* FILE Directory routines */
/* do a wild card directory search (for file name completion) */
char *getffile (char *fspec)
{
char fname[NFILEN]; /* file/path for dirscan() call */
char *name;
_kernel_osfile_block blk;
/* Add a "*" wildcard at the end */
strcpy(fname, fspec);
strcat(fname, "*");
/* Look for the next non-directory name */
name = dirscan(fname);
while (name && _kernel_osfile(17,name,&blk) != 1)
name = dirscan(0);
return (name);
}
char *getnfile (void)
{
char *name;
_kernel_osfile_block blk;
/* Look for the next non-directory name */
name = dirscan(0);
while (name && _kernel_osfile(17,name,&blk) != 1)
name = dirscan(0);
return (name);
}
#endif